//
//  MMCameraAndImagePickerViewController.m
//  MemeMaker
//
//  Created by dangthan on 7/30/13.
//  Copyright (c) 2013 soyo. All rights reserved.
//

#import "MMCameraAndImagePickerViewController.h"
#import "UIImage+Util.h"
#define kSizeCrop 480.0


@interface MMCameraAndImagePickerViewController ()
{
    
}
@end

@implementation MMCameraAndImagePickerViewController
@synthesize delegate;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self generateTopButtons];
    
    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
    [defaultCenter addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
    [btnTakeShot setExclusiveTouch:YES];
    [btnAlbum setExclusiveTouch:YES];
    

#if !TARGET_IPHONE_SIMULATOR
    NSError *err;
    if (!captureManager) {
        captureManager = [[MMCapture alloc] init];
    }
    
    [captureManager setDelegate:self];
    if ([captureManager setupSessionWithPreset:AVCaptureSessionPresetPhoto error:&err]) {
        if ([MMUtils isIPhone5]) {
            viewMainCamera = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 392.0f)];
        } else {
            viewMainCamera = [[UIView alloc] initWithFrame:CGRectMake(0.0f, -32.0f, 320.0f, 372.0f)];
        }
        [viewMainCamera setBackgroundColor:[UIColor clearColor]];
        [self.view addSubview:viewMainCamera];
        
        previewView = [[UIView alloc] initWithFrame:
                       CGRectMake(0, 0, viewMainCamera.frame.size.width,
                                  viewMainCamera.frame.size.height)];
        [previewView setBackgroundColor:[UIColor blackColor]];
        [viewMainCamera addSubview:previewView];
        
        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapToFocus:)];
        singleTap.numberOfTapsRequired = 1;
        singleTap.numberOfTouchesRequired = 1;
        [previewView addGestureRecognizer:singleTap];
        
        UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapToExpose:)];
        doubleTap.numberOfTapsRequired = 2;
        doubleTap.numberOfTouchesRequired = 1;
        [previewView addGestureRecognizer:doubleTap];
        
        [singleTap requireGestureRecognizerToFail:doubleTap];
        
        /***
         Create view opacity background of camera
         ****/
        CGRect bounds = previewView.bounds;
        previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureManager.capSession];
        previewLayer.frame = bounds;
        previewLayer.hidden = YES;
        
        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        
        NSDictionary *unanimatedActions = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"bounds", [NSNull null], @"frame", [NSNull null], @"position", nil];
        focusBox = [CALayer layer];
        focusBox.actions = unanimatedActions;
        focusBox.borderWidth = 2.0f;
        focusBox.borderColor = [[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.8f] CGColor];
        focusBox.opacity = 0.0f;
        [previewLayer addSublayer:focusBox];
        
        exposeBox = [CALayer layer];
        exposeBox.actions = unanimatedActions;
        exposeBox.borderWidth = 2.0f;
        exposeBox.borderColor = [[UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:0.8f] CGColor];
        exposeBox.opacity = 0.0f;
        [previewLayer addSublayer:exposeBox];
        
        [previewView.layer addSublayer:previewLayer];
    }
#endif
    
    if (captureManager && [captureManager hasMultipleCameras]) { //for multi camera
        btnChangeCamera.enabled = YES;
    } else {
        btnChangeCamera.enabled = NO;
    }
    UIImageView *cropFrameView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"crop_frame.png"]];
    if ([MMUtils isIPhone5]) {
        [cropFrameView setFrame:CGRectMake(0, 5.0, cropFrameView.frame.size.width, cropFrameView.frame.size.height)];
    }
    cropFrameView.alpha = 0.3f;
    [previewView addSubview:cropFrameView];
    
    [viewButton setFrame:CGRectMake(0, [MMUtils sizeWindowScreen].height - viewButton.frame.size.height, self.view.frame.size.width, viewButton.frame.size.height)];
    [self.view bringSubviewToFront:viewButton];

}

- (void) generateTopButtons
{
    UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(cancelClicked:)];
    [self.navigationItem setLeftBarButtonItem:btnDone];
    
    btnChangeCamera = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(changeCameraClicked:)];
    [self.navigationItem setRightBarButtonItem:btnChangeCamera];
}

- (void) viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
#if !TARGET_IPHONE_SIMULATOR
    [captureManager performSelector:@selector(startRunning) withObject:nil afterDelay:0.0];
#endif
}

- (void) viewWillDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
//#if !TARGET_IPHONE_SIMULATOR
//    previewLayer.hidden = YES;
//    [captureManager performSelector:@selector(stopRunning) withObject:nil afterDelay:0.0];
//#endif
}

- (void) viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}

- (void)viewDidUnload {
    btnChangeCamera = nil;
    [super viewDidUnload];
    btnTakeShot = nil;
    btnAlbum = nil;
    viewButton = nil;
    captureManager = nil;
    viewMainCamera = nil;
    previewLayer = nil;
    previewView = nil;
    imagePickerController = nil;
    viewButton = nil;
    focusBox = nil;
    exposeBox = nil;
}

#pragma mark - Private method
- (void) showImagePicker {
    if (!imagePickerController) {
        imagePickerController = [[UIImagePickerController alloc] init];
        imagePickerController.delegate = self;
        imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;//UIImagePickerControllerSourceTypeSavedPhotosAlbum; //
        imagePickerController.allowsEditing = NO;
    }
    
//    UIView *imagePickerView = imagePickerController.view;
//    
//    UIView *view = [imagePickerView hitTest:CGPointMake(5,5) withEvent:nil];
//    while (![view isKindOfClass:[UIScrollView class]] && view != nil) {
//        view = [view superview];
//    }
//    
//    if ([view isKindOfClass:[UIScrollView class]]) {
//        UIScrollView *scrollView = (UIScrollView *) view;
//        CGPoint contentOffset = scrollView.contentOffset;
//        CGFloat y = MAX(contentOffset.y, [scrollView contentSize].height-scrollView.frame.size.height);
//        CGPoint bottomOffset = CGPointMake(0, y);
//        [scrollView setContentOffset:bottomOffset animated:YES];
//    }
    
    [self presentViewController:imagePickerController animated:YES completion:^{
        processingTakePhoto = NO;
        [btnAlbum setEnabled:YES];
        [btnTakeShot setEnabled:YES];
    }];
}

- (void)_enableButton:(id)sender {
    UIButton *barButton = (UIButton*)sender;
    [barButton setEnabled:YES];
}

-(void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    //do smth
    [btnChangeCamera setEnabled:YES];
    [btnAlbum setEnabled:YES];
    [btnTakeShot setEnabled:YES];
}

- (void)hideImagePickerAnimated:(BOOL)animated {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)applicationDidEnterBackground:(NSNotification *)note {
    if (imagePickerController) {
        [self hideImagePickerAnimated:YES];
    }
    [self.navigationController popViewControllerAnimated:YES];
}

#pragma mark - ImagePikcer Delegate
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    UIImage *oriImage = [info valueForKey:UIImagePickerControllerOriginalImage];
    NSLog(@"imge with: %f and image height: %f", oriImage.size.width, oriImage.size.height);

    //crop
    
//    CGRect cropRect = [[info valueForKey:UIImagePickerControllerCropRect] CGRectValue];
//    cropRect = [oriImage convertedCropRect:cropRect];
//    UIImage *croppedImage = [oriImage croppedImageTo:cropRect];
//    UIImage *resizedImage = [croppedImage resizedImageCrop:CGSizeMake(kSizeCrop, kSizeCrop)
//                                      imageOrientation:oriImage.imageOrientation];

    //non crop
    UIImage *resizedImage = [oriImage resizedImageNonCrop:CGSizeMake(oriImage.size.width/3, oriImage.size.height/3)];
    
    [kMMManagerData setIsBackFromCamara:YES];
    [self dismissViewControllerAnimated:YES completion:nil];
    if (delegate && [delegate respondsToSelector:@selector(didReceivedImage:)]) {
        [delegate didReceivedImage:resizedImage];
    }
    [self.navigationController popViewControllerAnimated:NO];
}

- (void) imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self hideImagePickerAnimated:YES];
}

#pragma mark - IBAction
- (IBAction) btnClicked:(id) sender {
    UIButton *btn = (UIButton*)sender;
    if (btn.tag == 1) { //camera
        if (processingTakePhoto) {
            return;
        }
        
#if !TARGET_IPHONE_SIMULATOR
        [btnAlbum setEnabled:NO];
        [btnTakeShot setEnabled:NO];
        processingTakePhoto = YES;
        [captureManager captureStillImage];
#endif
    } else if (btn.tag == 2) { //album
        if (processingTakePhoto) {
            return;
        }
        processingTakePhoto = YES;
        [btnAlbum setEnabled:NO];
        [btnTakeShot setEnabled:NO];
        previewLayer.hidden = YES;
        [captureManager stopRunning];
        [self performSelector:@selector(showImagePicker) withObject:nil afterDelay:0.1];
    } else if (btn.tag == 3) { //frontToback
        if (processingTakePhoto) {
            return;
        }
        
    #if !TARGET_IPHONE_SIMULATOR
        previewLayer.hidden = YES;
        [captureManager stopRunning];
        [self performSelector:@selector(closeThisScreen) withObject:nil afterDelay:0.2];
    #else
        [self closeThisScreen];
    #endif
        
    } else { //back to front
        if (processingTakePhoto) {
            return;
        }
        [btnChangeCamera setEnabled:NO];
        [btnAlbum setEnabled:NO];
        [btnTakeShot setEnabled:NO];
        UIViewAnimationTransition typeAnimation = UIViewAnimationTransitionFlipFromLeft;
        
        AVCaptureDevicePosition position = captureManager.vInput.device.position;
        if (position == AVCaptureDevicePositionFront) {
            typeAnimation = UIViewAnimationTransitionFlipFromRight;
        }
        
        [captureManager cameraToggleClicked];
        
        [UIView beginAnimations:@"View Flip" context:nil];
        [UIView setAnimationDuration:0.6];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
        [UIView setAnimationTransition:typeAnimation
                               forView:viewMainCamera
                                 cache:YES];
        [UIView setAnimationDelegate:self];
        
        [previewView setHidden:YES];
        [UIView commitAnimations];
        
        [previewView setHidden:NO];
    }
}

- (void) closeThisScreen {
    UIViewController *controller = [self.navigationController popViewControllerAnimated:NO];
    if (!controller) {
//        [self dismissViewControllerAnimated:YES completion:nil];
        [self.navigationController popViewControllerAnimated:YES];
    }
}

- (void) backToMainViewController:(UIImage *)img {
//    [self dismissViewControllerAnimated:YES completion:nil];
    [self.navigationController popViewControllerAnimated:NO];
}

#pragma mark - MMCaptureDelegate
- (void) captureSessionDidStartRunning {
    previewLayer.hidden = NO;
    
    CGRect bounds = previewView.bounds;
    CGPoint screenCenter = CGPointMake(bounds.size.width / 2.0f, bounds.size.height / 2.0f);
    [self drawFocusBoxAtPointOfInterest:screenCenter];
    [self drawExposeBoxAtPointOfInterest:screenCenter];
}

- (void) captureStillImageFinished:(UIImage *)image {
    CGSize imageSize = image.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    
    //crop
//    CGRect cropRect;
//    if (height > width) {
//        cropRect = CGRectMake((height - width) / 2.0f, 0.0f, width, width);
//    } else {
//        cropRect = CGRectMake((width - height) / 2.0f, 0.0f, width, width);
//    }
//    
//    UIImage *croppedImage = [image croppedImageTo:cropRect];
//    UIImage *resizedImage = [croppedImage resizedImageCrop:CGSizeMake(kSizeCrop, kSizeCrop)
//        imageOrientation:image.imageOrientation];
    
    //non crop
    UIImage *resizedImage = [image resizedImageNonCrop:CGSizeMake(width/5, height/5)];
    
    [kMMManagerData setIsBackFromCamara:YES];
    
    if (delegate && [delegate respondsToSelector:@selector(didReceivedImage:)]) {
        [delegate didReceivedImage:resizedImage];
    }
    [self.navigationController popViewControllerAnimated:YES];

//    processingTakePhoto = NO;
//    [btnAlbum setEnabled:YES];
//    [btnTakeShot setEnabled:YES];
}

- (void)captureStillImageFailedWithError:(NSError *)error {
    [MMUtils showAlertView:@"" andMessage:[error localizedDescription]];
}
- (void)acquiringDeviceLockFailedWithError:(NSError *)error {
    [MMUtils showAlertView:@"" andMessage:[error localizedDescription]];
}

#pragma mark - Draw a view opacity background
+ (void)addAdjustingAnimationToLayer:(CALayer *)layer removeAnimation:(BOOL)remove {
    if (remove) {
        [layer removeAnimationForKey:@"animateOpacity"];
    }
    if ([layer animationForKey:@"animateOpacity"] == nil) {
        [layer setHidden:NO];
        CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        [opacityAnimation setDuration:0.3f];
        [opacityAnimation setRepeatCount:1.0f];
        [opacityAnimation setAutoreverses:YES];
        [opacityAnimation setFromValue:[NSNumber numberWithFloat:1.0f]];
        [opacityAnimation setToValue:[NSNumber numberWithFloat:0.0f]];
        [layer addAnimation:opacityAnimation forKey:@"animateOpacity"];
    }
}

- (void)drawFocusBoxAtPointOfInterest:(CGPoint)point {
    if ([captureManager hasFocus]) {
        [focusBox setFrame:CGRectMake(0.0f, 0.0f, 80.0f, 80.0f)];
        [focusBox setPosition:point];
        [MMCameraAndImagePickerViewController addAdjustingAnimationToLayer:focusBox removeAnimation:YES];
    }
}

- (void)drawExposeBoxAtPointOfInterest:(CGPoint)point {
    if ([captureManager hasExposure]) {
        [exposeBox setFrame:CGRectMake(0.0f, 0.0f, 114.0f, 114.0f)];
        [exposeBox setPosition:point];
        [MMCameraAndImagePickerViewController addAdjustingAnimationToLayer:exposeBox removeAnimation:YES];
    }
}

- (CGPoint)convertToPointOfInterestFromViewCoordinates:(CGPoint)viewCoordinates {
    CGPoint pointOfInterest = CGPointMake(0.5f, 0.5f);
    CGSize frameSize = previewView.frame.size;
    
    AVCaptureVideoPreviewLayer *videoPreviewLayer = previewLayer;
    
    if ([[videoPreviewLayer videoGravity] isEqualToString:AVLayerVideoGravityResize]) {
        pointOfInterest = CGPointMake(viewCoordinates.y / frameSize.height, 1.0f - (viewCoordinates.x / frameSize.width));
    } else {
        CGRect cleanAperture;
        for (AVCaptureInputPort *port in captureManager.vInput.ports) {
            if ([port mediaType] == AVMediaTypeVideo) {
                cleanAperture = CMVideoFormatDescriptionGetCleanAperture([port formatDescription], YES);
                CGSize apertureSize = cleanAperture.size;
                CGPoint point = viewCoordinates;
                
                CGFloat apertureRatio = apertureSize.height / apertureSize.width;
                CGFloat viewRatio = frameSize.width / frameSize.height;
                CGFloat xc = 0.5f;
                CGFloat yc = 0.5f;
                
                if ( [[videoPreviewLayer videoGravity] isEqualToString:AVLayerVideoGravityResizeAspect] ) {
                    if (viewRatio > apertureRatio) {
                        CGFloat y2 = frameSize.height;
                        CGFloat x2 = frameSize.height * apertureRatio;
                        CGFloat x1 = frameSize.width;
                        CGFloat blackBar = (x1 - x2) / 2;
                        if (point.x >= blackBar && point.x <= blackBar + x2) {
                            xc = point.y / y2;
                            yc = 1.0f - ((point.x - blackBar) / x2);
                        }
                    } else {
                        CGFloat y2 = frameSize.width / apertureRatio;
                        CGFloat y1 = frameSize.height;
                        CGFloat x2 = frameSize.width;
                        CGFloat blackBar = (y1 - y2) / 2;
                        if (point.y >= blackBar && point.y <= blackBar + y2) {
                            xc = ((point.y - blackBar) / y2);
                            yc = 1.0f - (point.x / x2);
                        }
                    }
                } else if ([[videoPreviewLayer videoGravity] isEqualToString:AVLayerVideoGravityResizeAspectFill]) {
                    if (viewRatio > apertureRatio) {
                        CGFloat y2 = apertureSize.width * (frameSize.width / apertureSize.height);
                        xc = (point.y + ((y2 - frameSize.height) / 2.0f)) / y2;
                        yc = (frameSize.width - point.x) / frameSize.width;
                    } else {
                        CGFloat x2 = apertureSize.height * (frameSize.height / apertureSize.width);
                        yc = 1.0f - ((point.x + ((x2 - frameSize.width) / 2)) / x2);
                        xc = point.y / frameSize.height;
                    }
                }
                
                pointOfInterest = CGPointMake(xc, yc);
                break;
            }
        }
    }
    
    return pointOfInterest;
}

#pragma mark - Tap handle
- (void)tapToFocus:(UIGestureRecognizer *)recognizer {
    CGPoint point = [recognizer locationInView:previewView];
    if (captureManager.vInput.device.isFocusPointOfInterestSupported) {
        CGPoint convertedFocusPoint = [self convertToPointOfInterestFromViewCoordinates:point];
        [captureManager focusAtPoint:convertedFocusPoint];
        [self drawFocusBoxAtPointOfInterest:point];
    }
}

- (void)tapToExpose:(UIGestureRecognizer *)recognizer {
    CGPoint point = [recognizer locationInView:previewView];
    if (captureManager.vInput.device.isExposurePointOfInterestSupported) {
        CGPoint convertedExposurePoint = [self convertToPointOfInterestFromViewCoordinates:point];
        [captureManager exposureAtPoint:convertedExposurePoint];
        [self drawExposeBoxAtPointOfInterest:point];
    }
}

- (void)resetFocusAndExpose:(UIGestureRecognizer *)recognizer {
    CGPoint pointOfInterest = CGPointMake(0.5f, 0.5f);
    [captureManager focusAtPoint:pointOfInterest];
    [captureManager exposureAtPoint:pointOfInterest];
    
    CGRect bounds = previewView.bounds;
    CGPoint screenCenter = CGPointMake(bounds.size.width / 2.0f, bounds.size.height / 2.0f);
    
    [self drawFocusBoxAtPointOfInterest:screenCenter];
    [self drawExposeBoxAtPointOfInterest:screenCenter];
    
    [captureManager setFocus:AVCaptureFocusModeContinuousAutoFocus];
}


- (void)changeCameraClicked:(id)sender {
    if (processingTakePhoto) {
        return;
    }
    
    [btnAlbum setEnabled:NO];
    [btnTakeShot setEnabled:NO];
    UIViewAnimationTransition typeAnimation = UIViewAnimationTransitionFlipFromLeft;
    
    AVCaptureDevicePosition position = captureManager.vInput.device.position;
    if (position == AVCaptureDevicePositionFront) {
        typeAnimation = UIViewAnimationTransitionFlipFromRight;
    }
    
    [captureManager cameraToggleClicked];
    
    [UIView beginAnimations:@"View Flip" context:nil];
    [UIView setAnimationDuration:0.6];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
    [UIView setAnimationTransition:typeAnimation
                           forView:viewMainCamera
                             cache:YES];
    [UIView setAnimationDelegate:self];
    
    [previewView setHidden:YES];
    [UIView commitAnimations];
    
    [previewView setHidden:NO];
}

- (void)cancelClicked:(id)sender {
    if (processingTakePhoto) {
        return;
    }
    
#if !TARGET_IPHONE_SIMULATOR
    previewLayer.hidden = YES;
    [captureManager stopRunning];
//    [self performSelector:@selector(closeThisScreen) withObject:nil afterDelay:0.2];
    [self.navigationController popViewControllerAnimated:YES];
#else
    [self.navigationController popViewControllerAnimated:YES];
#endif
}

- (void) dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
